#!sicp

(define exc
(+ (* 3
      (+ (* 2 4)
         (+ 3 5)))
   (+ (- 10 7)
       6)))

(display exc)

(define (square x) (* x x))
(define (square-sum x y) (+ (square x) (square y)))
(define (f x)
    (square-sum (+ x 5) (* x 5)))

(define (abs x)
    (cond ((> x 0) x)
          ((= x 0) 0)
          ((< x 0) (- x))))

;1.2
(define e1.2 (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7))))
(display e1.2)

;1.3
(define (trsum x y z)
    (cond ((or (and (> x y) (> y z)) 
               (and (> y x) (> x z))) 
                    (+ x y))
          ((or (and (> x z) (> z y)) 
               (and (> z x) (> x y))) 
                    (+ x z))
          ((or (and (> y z) (> z x)) 
               (and (> z y) (> y x))) 
                    (+ y z))))

;1.4
(define (a-plus-abs-b a b)
    ((if (> b 0) + -) a b))

(define (p) (p))

(define (test x y)
    (if (= x 0)
        0
        y))

;1.1.7
(define (sqrt-iter guess x)
    (display guess)
    (if (good-enough? guess (improve guess x))
        (improve guess x)
        (sqrt-iter (improve guess x)
                x)))

(define (improve guess x)
    (average guess (/ x guess)))

(define (average x y)
    (/ (+ x y) 2))

;对于很小的数，或者很大的数，检测可能出问题
;(define (good-enough? guess x)
;    (< (abs (- (square guess) x)) 0.000000000001))
(define (good-enough? old-guess new-guess)
    (> 0.001
    (/ (abs (- new-guess old-guess))
        old-guess)))

(define (sqrt x)
    (sqrt-iter 1.0 x))

;1.6
(define (new-if predicate then-clause else-clause)
    (cond (predicate then-clause)
          (else else-clause)))

;1.8
(define (cube-iter guess x)
    (display guess)
    (if (good-enough? guess (cube-improve guess x))
        (cube-improve guess x)
        (cube-iter (cube-improve guess x)
            x)))
(define (cube-improve guess x)
    (/ (+ (/ x (* guess guess)) (* 2 guess)) 3))

(define (cube x)
    (cube-iter 1.0 x))

;1.10
(define (A x y)
    (display x y)
    (cond ((= y 0) 0)
          ((= x 0) (* 2 y))
          ((= y 1) 2)
          (else (A (- x 1)
            (A x (- y 1))))))

;change
(define (count-change amount)
    (cc amount 5))

(define (cc amount kinds-of-coins)
    (cond ((= amount 0) 1)
          ((or (< amount 0) (= kinds-of-coins 0)) 0)
          (else (+ (cc amount
                        (- kinds-of-coins 1))
                   (cc (- amount (first-denomination kinds-of-coins))
                        kinds-of-coins)))))
(define (first-denomination kinds-of-coins)
    (cond ((= kinds-of-coins 1) 1)
          ((= kinds-of-coins 2) 5)
          ((= kinds-of-coins 3) 10)
          ((= kinds-of-coins 4) 25)
          ((= kinds-of-coins 5) 50)))

;1.11
(define (f-recursion n)
    (cond ((< n 3) n)
          (else (+ (f-recursion (- n 1)) 
                (* 2 (f-recursion (- n 2))) 
                (* 3 (f-recursion (- n 3)))))))

(define (f-iteration n)
    (f-iter 2 1 0 0 n))

(define (f-iter a b c i n)
    (cond ((= i n) c)
    (else (f-iter (+ a (* 2 b) (* 3 c)) 
                  a 
                  b 
                  (+ i 1) 
                  n))))

;1.12
(define (pascal row col)
    (cond ((> col row)
        (error "unvalid col value"))
          ((or (= col 0) (= col row))
          1)
          (else (+ (pascal (- row 1) (- col 1))
                   (pascal (- row 1) col)))))

(define (factorial n)
    (fact-iter 1 1 n))

(define (fact-iter product counter max-count)
    (cond ((> counter max-count) product)
          (else (fact-iter (* counter product)
                           (+ counter 1)
                           max-count))))

(define (pascal-iteration row col)
    (/ (factorial row) (* (factorial col) (factorial (- row col)))))

(define (gcd a b)
    (cond ((= b 0) a)
          (else (gcd b (remainder a b)))))

(define (sum term a next b)
    (if (> a b)
        0
        (+ (term a)
           (sum term (next a) next b))))

(define (inc n) (+ n 1))
(define (sum-cubes a b)
    sum cube a inc b)

(define (identity x) x)
(define (sum-integers a b)
    (sum identity a inc b))

(define (pi-sum a b)
    (define (pi-term x)
        (/ 1.0 (* x (+ x 2))))
    (define (pi-next x)
        (+ x 4))
    (sum pi-term a pi-next b))

(define (integral f a b dx)
    (define (add-dx x)
        (+ x dx))
    (* (sum f (+ a (/ dx 2.0)) add-dx b)
        dx))
;1.29
(define (simpson f a b n)
    (define h (/ (- b a) n))
    (define (y k) (f (+ a (* k h))))
    (define (factor k)
        (cond ((or (= k 0) (= k n))
            1)
            ((odd? k) 4)
            (else 2)))
    (define (term k)
        (* (factor k)
            (y k)))
    (define (next k) (+ k 1))
    (if (not (even? n))
        (error "n can not be odd")
        (* (/ h 3)
            (sum term (exact->inexact 0) next n))))

;1.30
;; (define (sum term a next b)
;;     (define (iter a result)
;;         (if (> a b)
;;             result
;;             (iter (next a)
;;                 (+ (term a) result))))
;;     (iter a 0))

;1.31
;; (define (product term a next b)
;;     (if (> a b) 1
;;         (* (term a)
;;             (product term (next a) next b))))

;; (define (product term a next b)
;;     (define (iter a result)
;;         (if (> a b) result
;;             (iter (next a)
;;                 (* (term a) result)))))

(define (numer-term i)
    (cond ((= i 1) 2)
          ((even? i) (+ i 2))
          (else (+ i 1))))

(define (denom-term i)
    (if (odd? i) (+ i 2)
        (+ i 1)))

;; (define (pi n)
;;     (* 4 
;;         (exact-inexact
;;             (/ (product numer-term 1 (lambda (i) (+ i 1)) n)
;;                 (product denom-term 1 (lambda (i) (+ i 1)) n)))))

;; (define (f x y)
;;     (define (f-helper a b)
;;         (+ (* x (square a))
;;            (* y b)
;;            (* a b)))
;;     (f-helper (+ 1 (* x y))
;;               (- 1 y)))
;; 
;; (define (f x y)
;;     ((lambda (a b)
;;         (+ (* x (square a))
;;            (* y b)
;;            (* a b)))
;;     (+ 1 (* x y))
;;     (- 1 y)))

;; (define (f x y)
;;     (let ((a (+ 1 (* xy)))
;;           (b (- 1 y)))
;;     (+ (* x (square a))
;;        (* y b)
;;        (* a b))))